// Thud - a dynamic object-oriented language
// Copyright (C) 2009,2010 David H. Hovemeyer <david.hovemeyer@gmail.com>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#ifndef VM_CLASS_H
#define VM_CLASS_H

#include <cstdint>
#include <string>
#include <vector>
#include "IPersistent.h"

class Field;
class Method;
class ConstantPool;

/**
 * A bytecode class.
 */
class Class : public IPersistent {
public:
	typedef std::vector<Field *> FieldList;
	typedef std::vector<Method *> MethodList;

private:
	uint32_t m_flags;
	std::wstring m_clsName;
	ConstantPool *m_constantPool;
	FieldList m_fieldList;
	MethodList m_methodList;

	Class(const Class &other);
	Class& operator=(const Class &);

public:
	/**
	 * Default constructor.
	 */
	Class();

	/**
	 * Constructor.
	 * @param flags   class flags
	 * @param clsName fully-qualified class name
	 */
	Class(uint32_t flags, const std::wstring &clsName);

	/** Destructor. */
	~Class();

	/**
	 * Set class flags.
	 * @param flags the flags to set
	 */
	void setFlags(uint32_t flags);

	/**
	 * Get the class flags.
	 */
	uint32_t getFlags() const;

	/**
	 * Get the fully-qualified class name.
	 */
	const std::wstring &getClassName() const;

	/**
	 * Set the fully-qualified class name.
	 */
	void setClassName(const std::wstring &clsName);

	/**
	 * Get the class's ConstantPool.
	 */
	ConstantPool* getConstantPool() { return m_constantPool; }

	/**
	 * Get the class's ConstantPool.
	 */
	const ConstantPool* getConstantPool() const { return m_constantPool; }

	/**
	 * Adopt given Field.
	 *
	 * @param field the Field to adopt
	 */
	void addAndAdoptField(Field *field);

	/**
	 * Adopt given Method.
	 *
	 * @param method the Method to adopt
	 */
	void addAndAdoptMethod(Method *method);

	/**
	 * Get list of Fields.
	 */
	FieldList& getFields();

	/**
	 * Get list of Methods.
	 */
	MethodList& getMethods();

	/**
	 * Find the Method with given name.
	 * Throws exception if method does not exist in this class.
	 *
	 * @param methodName name of Method
	 */
	Method *findMethod(const std::wstring &methodName);

	/**
	 * Find the "main$" method.
	 * Throws exception if there is no "main$" method in this class.
	 */
	Method *findMainMethod() { return findMethod(L"main$"); }

	/**
	 * Return true if given method exists in this class, false otherwise.
	 *
	 * @param methodName
	 */
	bool hasMethod(const std::wstring &methodName);

	virtual void read(DataInputStream *in);
	virtual void write(DataOutputStream *out) const;
};

#endif // VM_CLASS_H
